#include "angelscript_base.hpp"
#include "angelscript.h"
#include "angelscript/add_on/datetime/datetime.h"
#include "angelscript/add_on/scriptany/scriptany.h"
#include "angelscript/add_on/scriptarray/scriptarray.h"
#include "angelscript/add_on/scriptdictionary/scriptdictionary.h"
#include "angelscript/add_on/scriptfile/scriptfile.h"
#include "angelscript/add_on/scriptfile/scriptfilesystem.h"
#include "angelscript/add_on/scriptgrid/scriptgrid.h"
#include "angelscript/add_on/scripthandle/scripthandle.h"
#include "angelscript/add_on/scriptmath/scriptmath.h"
#include "angelscript/add_on/scriptmath/scriptmathcomplex.h"
#include "angelscript/add_on/scriptstdstring/scriptstdstring.h"
#include "angelscript/add_on/weakref/weakref.h"
#include "vm_type_register.hpp"

#include <fmt/format.h>

asIScriptEngine *AngelScriptShared::GetEngine ()
{
    static AngelScriptShared instance;
    return instance.the_engine;
}

// Implement a simple message callback function
static void MessageCallback(const asSMessageInfo *msg, void *param)
{
  const char *type = "ERR ";
  if( msg->type == asMSGTYPE_WARNING ) 
    type = "WARN";
  else if( msg->type == asMSGTYPE_INFORMATION ) 
    type = "INFO";
  printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);
}
 

AngelScriptShared::AngelScriptShared () : the_engine (asCreateScriptEngine ())
{
    // message callback
    the_engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL);

    // standard types
    RegisterScriptDateTime (the_engine);
    RegisterScriptAny (the_engine);
    RegisterScriptArray (the_engine, true);
    RegisterScriptGrid (the_engine);
    RegisterScriptHandle (the_engine);
    RegisterScriptMath (the_engine);
    RegisterScriptMathComplex (the_engine);
    RegisterStdString (the_engine);
    RegisterStdStringUtils (the_engine);
    RegisterScriptFile (the_engine);
    RegisterScriptFileSystem (the_engine);
    RegisterScriptWeakRef (the_engine);
    RegisterScriptDictionary (the_engine);

    RegisterTypes (the_engine);
}

AngelScriptShared::~AngelScriptShared ()
{
    the_engine->ShutDownAndRelease ();
}

AngelScriptBase::AngelScriptBase (const std::string &script_path, const std::string &cat) :
    module_name (fmt::format ("{}_{}", cat, std::hash<std::string> {}(script_path)))
{
}
